package sms_api

import (
	"context"
	"fmt"
	"strings"
	"sync"
	"time"

	"github.com/gogf/gf/v2/container/gmap"
	"github.com/gogf/gf/v2/os/glog"
	"github.com/gogf/gf/v2/os/gmutex"
	"github.com/gogf/gf/v2/util/gconv"

	"./providers"
)

// SMSService SMS服务
type SMSService struct {
	config    *Config
	providers *gmap.StrAnyMap
	cache     *gmap.StrAnyMap
	metrics   *Metrics
	retry     *RetryManager
	limiter   *RateLimiter
	circuit   *CircuitBreaker
	mu        *gmutex.Mutex
	logger    *glog.Logger
}

// Metrics 指标统计
type Metrics struct {
	TotalRequests    int64     `json:"total_requests"`
	SuccessRequests  int64     `json:"success_requests"`
	FailedRequests   int64     `json:"failed_requests"`
	TotalCost        float64   `json:"total_cost"`
	AverageLatency   float64   `json:"average_latency"`
	LastRequestTime  time.Time `json:"last_request_time"`
	ProviderMetrics  map[string]*ProviderMetrics `json:"provider_metrics"`
	mu               sync.RWMutex
}

// ProviderMetrics 提供商指标
type ProviderMetrics struct {
	Requests      int64   `json:"requests"`
	Successes     int64   `json:"successes"`
	Failures      int64   `json:"failures"`
	Cost          float64 `json:"cost"`
	AverageLatency float64 `json:"average_latency"`
	LastUsed      time.Time `json:"last_used"`
}

// RetryManager 重试管理器
type RetryManager struct {
	maxRetries int
	baseDelay  time.Duration
	maxDelay   time.Duration
	multiplier float64
}

// RateLimiter 速率限制器
type RateLimiter struct {
	requests *gmap.StrIntMap
	limit    int
	window   time.Duration
	mu       sync.RWMutex
}

// CircuitBreaker 熔断器
type CircuitBreaker struct {
	failureThreshold int
	resetTimeout     time.Duration
	state           string // "closed", "open", "half-open"
	failureCount    int
	lastFailureTime time.Time
	mu              sync.RWMutex
}

// NewSMSService 创建SMS服务实例
func NewSMSService(config *Config) (*SMSService, error) {
	if config == nil {
		return nil, NewValidationError("CONFIG_REQUIRED", "配置不能为空", nil)
	}

	// 验证配置
	if err := config.Validate(); err != nil {
		return nil, err
	}

	service := &SMSService{
		config:    config,
		providers: gmap.NewStrAnyMap(true),
		cache:     gmap.NewStrAnyMap(true),
		mu:        gmutex.New(),
		logger:    glog.New(),
	}

	// 初始化指标
	service.metrics = &Metrics{
		ProviderMetrics: make(map[string]*ProviderMetrics),
	}

	// 初始化重试管理器
	service.retry = &RetryManager{
		maxRetries: config.Retry.MaxRetries,
		baseDelay:  config.Retry.BaseDelay,
		maxDelay:   config.Retry.MaxDelay,
		multiplier: config.Retry.Multiplier,
	}

	// 初始化速率限制器
	service.limiter = &RateLimiter{
		requests: gmap.NewStrIntMap(true),
		limit:    config.RateLimit.RequestsPerSecond,
		window:   time.Second,
	}

	// 初始化熔断器
	service.circuit = &CircuitBreaker{
		failureThreshold: config.CircuitBreaker.FailureThreshold,
		resetTimeout:     config.CircuitBreaker.ResetTimeout,
		state:           "closed",
	}

	// 初始化提供商
	if err := service.initProviders(); err != nil {
		return nil, err
	}

	return service, nil
}

// initProviders 初始化提供商
func (s *SMSService) initProviders() error {
	// 初始化Space IoT提供商
	if s.config.SpaceIoT.Enabled {
		spaceConfig := &providers.SpaceIoTConfig{
			BaseURL: s.config.SpaceIoT.BaseURL,
			Sign:    s.config.SpaceIoT.Sign,
			Key:     s.config.SpaceIoT.Key,
			Timeout: s.config.SpaceIoT.Timeout,
		}
		provider := providers.NewSpaceIoTProvider(spaceConfig)
		if err := provider.ValidateConfig(); err != nil {
			return fmt.Errorf("Space IoT配置验证失败: %w", err)
		}
		s.providers.Set("space_iot", provider)
		s.metrics.ProviderMetrics["space_iot"] = &ProviderMetrics{}
	}

	// TODO: 添加其他提供商（阿里云、腾讯云、华为云等）

	if s.providers.Size() == 0 {
		return NewValidationError("NO_PROVIDERS", "至少需要启用一个SMS提供商", nil)
	}

	return nil
}

// SendSMS 发送单条短信
func (s *SMSService) SendSMS(ctx context.Context, req *SendSMSRequest) (*SendSMSResponse, error) {
	// 验证请求
	if err := req.Validate(); err != nil {
		return nil, err
	}

	// 检查速率限制
	if !s.checkRateLimit(req.Phone) {
		return nil, NewRateLimitError("RATE_LIMIT_EXCEEDED", "发送频率超限", time.Second)
	}

	// 检查熔断器
	if !s.checkCircuitBreaker() {
		return nil, NewCircuitOpenError("CIRCUIT_OPEN", "熔断器开启，暂停服务")
	}

	// 更新指标
	s.updateMetrics("request", "", 0, 0)

	// 获取提供商
	provider, err := s.getProvider(req.Provider)
	if err != nil {
		s.updateMetrics("failure", req.Provider, 0, 0)
		return nil, err
	}

	// 执行发送（带重试）
	start := time.Now()
	resp, err := s.executeWithRetry(ctx, func() (*SendSMSResponse, error) {
		return provider.SendSMS(ctx, &providers.SendSMSRequest{
			Phone:     req.Phone,
			Content:   req.Content,
			Sign:      req.Sign,
			Type:      req.Type,
			Priority:  req.Priority,
			MessageID: req.MessageID,
			Metadata:  req.Metadata,
		})
	})
	latency := time.Since(start)

	if err != nil {
		s.updateMetrics("failure", req.Provider, latency.Seconds(), 0)
		s.recordCircuitBreakerFailure()
		return nil, err
	}

	// 更新成功指标
	s.updateMetrics("success", req.Provider, latency.Seconds(), resp.Cost)
	s.recordCircuitBreakerSuccess()

	// 缓存结果
	s.cacheResponse(req.MessageID, resp)

	return resp, nil
}

// SendBatchSMS 批量发送短信
func (s *SMSService) SendBatchSMS(ctx context.Context, req *BatchSMSRequest) (*BatchSMSResponse, error) {
	// 验证批量请求
	if err := req.Validate(); err != nil {
		return nil, err
	}

	// 检查批量大小限制
	if len(req.Requests) > s.config.Batch.MaxSize {
		return nil, NewValidationError("BATCH_SIZE_EXCEEDED", 
			fmt.Sprintf("批量大小超限，最大允许%d条", s.config.Batch.MaxSize), nil)
	}

	// 获取提供商
	provider, err := s.getProvider(req.Provider)
	if err != nil {
		return nil, err
	}

	// 执行批量发送
	start := time.Now()
	resp, err := provider.SendBatchSMS(ctx, &providers.BatchSMSRequest{
		BatchID:   req.BatchID,
		Requests:  s.convertToProviderRequests(req.Requests),
		Provider:  req.Provider,
		Metadata:  req.Metadata,
	})
	latency := time.Since(start)

	if err != nil {
		s.updateMetrics("failure", req.Provider, latency.Seconds(), 0)
		return nil, err
	}

	// 更新指标
	s.updateMetrics("success", req.Provider, latency.Seconds(), resp.Cost)

	return &BatchSMSResponse{
		BatchID:    resp.BatchID,
		Total:      resp.Total,
		Success:    resp.Success,
		Failed:     resp.Failed,
		Results:    s.convertFromProviderResults(resp.Results),
		StartedAt:  resp.StartedAt,
		FinishedAt: resp.FinishedAt,
		Cost:       resp.Cost,
	}, nil
}

// QuerySMS 查询短信状态
func (s *SMSService) QuerySMS(ctx context.Context, req *QuerySMSRequest) (*QuerySMSResponse, error) {
	// 验证查询请求
	if err := req.Validate(); err != nil {
		return nil, err
	}

	// 先从缓存查找
	if cached := s.getCachedResponse(req.MessageID); cached != nil {
		return &QuerySMSResponse{
			MessageID:  req.MessageID,
			ProviderID: cached.ProviderID,
			Phone:      req.Phone,
			Status:     cached.Status,
			SentAt:     &cached.SentAt,
		}, nil
	}

	// 获取提供商
	provider, err := s.getProvider(req.Provider)
	if err != nil {
		return nil, err
	}

	// 查询状态
	resp, err := provider.QuerySMS(ctx, &providers.QuerySMSRequest{
		MessageID:  req.MessageID,
		ProviderID: req.ProviderID,
		Phone:      req.Phone,
	})
	if err != nil {
		return nil, err
	}

	return &QuerySMSResponse{
		MessageID:     resp.MessageID,
		ProviderID:    resp.ProviderID,
		Phone:         resp.Phone,
		Status:        resp.Status,
		SentAt:        resp.SentAt,
		DeliveredAt:   resp.DeliveredAt,
		ErrorCode:     resp.ErrorCode,
		ErrorMessage:  resp.ErrorMessage,
	}, nil
}

// GetMetrics 获取指标
func (s *SMSService) GetMetrics() *MetricsResponse {
	s.metrics.mu.RLock()
	defer s.metrics.mu.RUnlock()

	successRate := 0.0
	if s.metrics.TotalRequests > 0 {
		successRate = float64(s.metrics.SuccessRequests) / float64(s.metrics.TotalRequests) * 100
	}

	return &MetricsResponse{
		TotalRequests:   s.metrics.TotalRequests,
		SuccessRequests: s.metrics.SuccessRequests,
		FailedRequests:  s.metrics.FailedRequests,
		SuccessRate:     successRate,
		TotalCost:       s.metrics.TotalCost,
		AverageLatency:  s.metrics.AverageLatency,
		LastRequestTime: s.metrics.LastRequestTime,
		Providers:       s.getProviderMetrics(),
	}
}

// HealthCheck 健康检查
func (s *SMSService) HealthCheck(ctx context.Context) *HealthResponse {
	status := "healthy"
	providerStatus := make(map[string]string)

	// 检查每个提供商
	s.providers.Iterator(func(name string, provider interface{}) bool {
		if p, ok := provider.(providers.SMSProvider); ok {
			if err := p.HealthCheck(ctx); err != nil {
				providerStatus[name] = "unhealthy: " + err.Error()
				status = "degraded"
			} else {
				providerStatus[name] = "healthy"
			}
		}
		return true
	})

	// 检查熔断器状态
	circuitStatus := s.circuit.state
	if circuitStatus == "open" {
		status = "unhealthy"
	}

	return &HealthResponse{
		Status:         status,
		Timestamp:      time.Now(),
		Version:        "1.0.0",
		Providers:      providerStatus,
		CircuitBreaker: circuitStatus,
		Uptime:         time.Since(time.Now()).String(), // 简化实现
	}
}

// getProvider 获取提供商
func (s *SMSService) getProvider(name string) (providers.SMSProvider, error) {
	if name == "" {
		name = s.config.DefaultProvider
	}

	provider := s.providers.Get(name)
	if provider == nil {
		return nil, NewProviderError("PROVIDER_NOT_FOUND", 
			fmt.Sprintf("提供商 %s 未找到", name), false)
	}

	p, ok := provider.(providers.SMSProvider)
	if !ok {
		return nil, NewProviderError("INVALID_PROVIDER", 
			fmt.Sprintf("提供商 %s 类型无效", name), false)
	}

	return p, nil
}

// executeWithRetry 执行带重试的操作
func (s *SMSService) executeWithRetry(ctx context.Context, fn func() (*SendSMSResponse, error)) (*SendSMSResponse, error) {
	var lastErr error
	delay := s.retry.baseDelay

	for attempt := 0; attempt <= s.retry.maxRetries; attempt++ {
		if attempt > 0 {
			// 等待重试延迟
			select {
			case <-ctx.Done():
				return nil, NewTimeoutError("CONTEXT_CANCELLED", "上下文已取消")
			case <-time.After(delay):
				// 指数退避
				delay = time.Duration(float64(delay) * s.retry.multiplier)
				if delay > s.retry.maxDelay {
					delay = s.retry.maxDelay
				}
			}
		}

		resp, err := fn()
		if err == nil {
			return resp, nil
		}

		lastErr = err

		// 检查是否可重试
		if !s.isRetryableError(err) {
			break
		}
	}

	return nil, lastErr
}

// isRetryableError 判断错误是否可重试
func (s *SMSService) isRetryableError(err error) bool {
	if smsErr, ok := err.(SMSError); ok {
		return smsErr.IsRetryable()
	}
	return false
}

// checkRateLimit 检查速率限制
func (s *SMSService) checkRateLimit(phone string) bool {
	s.limiter.mu.Lock()
	defer s.limiter.mu.Unlock()

	now := time.Now()
	key := fmt.Sprintf("%s_%d", phone, now.Unix())

	count := s.limiter.requests.Get(key)
	if count >= s.limiter.limit {
		return false
	}

	s.limiter.requests.Set(key, count+1)

	// 清理过期的记录
	go s.cleanupRateLimit()

	return true
}

// cleanupRateLimit 清理速率限制记录
func (s *SMSService) cleanupRateLimit() {
	now := time.Now()
	expired := now.Add(-s.limiter.window).Unix()

	s.limiter.requests.Iterator(func(key string, value int) bool {
		// 解析时间戳
		parts := strings.Split(key, "_")
		if len(parts) >= 2 {
			if timestamp := gconv.Int64(parts[len(parts)-1]); timestamp < expired {
				s.limiter.requests.Remove(key)
			}
		}
		return true
	})
}

// checkCircuitBreaker 检查熔断器
func (s *SMSService) checkCircuitBreaker() bool {
	s.circuit.mu.RLock()
	defer s.circuit.mu.RUnlock()

	switch s.circuit.state {
	case "closed":
		return true
	case "open":
		// 检查是否可以进入半开状态
		if time.Since(s.circuit.lastFailureTime) > s.circuit.resetTimeout {
			s.circuit.state = "half-open"
			return true
		}
		return false
	case "half-open":
		return true
	default:
		return false
	}
}

// recordCircuitBreakerFailure 记录熔断器失败
func (s *SMSService) recordCircuitBreakerFailure() {
	s.circuit.mu.Lock()
	defer s.circuit.mu.Unlock()

	s.circuit.failureCount++
	s.circuit.lastFailureTime = time.Now()

	if s.circuit.failureCount >= s.circuit.failureThreshold {
		s.circuit.state = "open"
	}
}

// recordCircuitBreakerSuccess 记录熔断器成功
func (s *SMSService) recordCircuitBreakerSuccess() {
	s.circuit.mu.Lock()
	defer s.circuit.mu.Unlock()

	if s.circuit.state == "half-open" {
		s.circuit.state = "closed"
		s.circuit.failureCount = 0
	}
}

// updateMetrics 更新指标
func (s *SMSService) updateMetrics(action, provider string, latency, cost float64) {
	s.metrics.mu.Lock()
	defer s.metrics.mu.Unlock()

	switch action {
	case "request":
		s.metrics.TotalRequests++
		s.metrics.LastRequestTime = time.Now()
	case "success":
		s.metrics.SuccessRequests++
		s.metrics.TotalCost += cost
		s.updateProviderMetrics(provider, true, latency, cost)
	case "failure":
		s.metrics.FailedRequests++
		s.updateProviderMetrics(provider, false, latency, 0)
	}

	// 更新平均延迟
	if s.metrics.TotalRequests > 0 {
		s.metrics.AverageLatency = (s.metrics.AverageLatency*float64(s.metrics.TotalRequests-1) + latency) / float64(s.metrics.TotalRequests)
	}
}

// updateProviderMetrics 更新提供商指标
func (s *SMSService) updateProviderMetrics(provider string, success bool, latency, cost float64) {
	if provider == "" {
		return
	}

	metrics, exists := s.metrics.ProviderMetrics[provider]
	if !exists {
		metrics = &ProviderMetrics{}
		s.metrics.ProviderMetrics[provider] = metrics
	}

	metrics.Requests++
	metrics.LastUsed = time.Now()
	metrics.Cost += cost

	if success {
		metrics.Successes++
	} else {
		metrics.Failures++
	}

	// 更新平均延迟
	if metrics.Requests > 0 {
		metrics.AverageLatency = (metrics.AverageLatency*float64(metrics.Requests-1) + latency) / float64(metrics.Requests)
	}
}

// getProviderMetrics 获取提供商指标
func (s *SMSService) getProviderMetrics() map[string]interface{} {
	result := make(map[string]interface{})
	for name, metrics := range s.metrics.ProviderMetrics {
		successRate := 0.0
		if metrics.Requests > 0 {
			successRate = float64(metrics.Successes) / float64(metrics.Requests) * 100
		}

		result[name] = map[string]interface{}{
			"requests":        metrics.Requests,
			"successes":       metrics.Successes,
			"failures":        metrics.Failures,
			"success_rate":    successRate,
			"cost":            metrics.Cost,
			"average_latency": metrics.AverageLatency,
			"last_used":       metrics.LastUsed,
		}
	}
	return result
}

// cacheResponse 缓存响应
func (s *SMSService) cacheResponse(messageID string, resp *SendSMSResponse) {
	if s.config.Cache.Enabled {
		s.cache.Set(messageID, resp)
		// 设置过期时间
		go func() {
			time.Sleep(s.config.Cache.TTL)
			s.cache.Remove(messageID)
		}()
	}
}

// getCachedResponse 获取缓存响应
func (s *SMSService) getCachedResponse(messageID string) *SendSMSResponse {
	if !s.config.Cache.Enabled {
		return nil
	}

	if cached := s.cache.Get(messageID); cached != nil {
		if resp, ok := cached.(*SendSMSResponse); ok {
			return resp
		}
	}
	return nil
}

// convertToProviderRequests 转换为提供商请求
func (s *SMSService) convertToProviderRequests(requests []*SendSMSRequest) []*providers.SendSMSRequest {
	result := make([]*providers.SendSMSRequest, len(requests))
	for i, req := range requests {
		result[i] = &providers.SendSMSRequest{
			Phone:     req.Phone,
			Content:   req.Content,
			Sign:      req.Sign,
			Type:      req.Type,
			Priority:  req.Priority,
			MessageID: req.MessageID,
			Metadata:  req.Metadata,
		}
	}
	return result
}

// convertFromProviderResults 转换提供商结果
func (s *SMSService) convertFromProviderResults(results []*providers.BatchSMSResult) []*BatchSMSResult {
	converted := make([]*BatchSMSResult, len(results))
	for i, result := range results {
		converted[i] = &BatchSMSResult{
			Index:        result.Index,
			MessageID:    result.MessageID,
			ProviderID:   result.ProviderID,
			Phone:        result.Phone,
			Status:       result.Status,
			Cost:         result.Cost,
			SentAt:       result.SentAt,
			ErrorCode:    result.ErrorCode,
			ErrorMessage: result.ErrorMessage,
		}
	}
	return converted
}